﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Sustainalytics.ClientDW.Entities;
using Sustainalytics.ESGRatings.BusinessLogic.Models;
using Sustainalytics.ESGRatings.Service.Models.Common;
using Sustainalytics.ESGRatings.Service.Models.DTOs.RpIndicators;
using Sustainalytics.Utils;

namespace Sustainalytics.ESGRatings.Service.Models
{
    public static class DomainModelToDtoUtils
    {
        public static EsgThemeOverallPerformanceSummaryDto ToDto(this BusinessLogic.ESGOnlineReport.ThemePerformance domainModel)
        {
            if (domainModel == null)
                return null;

            var result = new EsgThemeOverallPerformanceSummaryDto
            {
                Theme = GetEsgTheme(domainModel.ThemeName),
                Overall = new EsgThemeOverallScoreSummaryDto
                {
                    Score = Convert.ToDecimal(domainModel.Performance.Score),
                    EsgPosition = domainModel.Performance.Assessment,

                },
                Relative = new EsgThemeRelativePositionSummaryDto
                {
                    ComparativeGroupRank = domainModel.Performance.Rank.Value.GetValueOrDefault(),
                    ComparativeGroupSize = domainModel.Performance.GroupCount,
                    IsInReferenceUniverse = domainModel.IsInReferenceUniverse
                },
                Weight = new EsgThemeWeightSummaryDto
                {
                    Weight = Convert.ToDecimal(domainModel.Performance.Weight)
                },
                Percentile = new EsgThemePercentileSummaryDto
                {
                    ComparativeGroupPercentileRank = (int)Math.Round(domainModel.Performance.Percentile, 0, MidpointRounding.AwayFromZero),
                    IsInReferenceUniverse = domainModel.IsInReferenceUniverse
                }
            };

            return result;
        }

        private static EsgThemeEnum GetEsgTheme(string themeName)
        {
            EsgThemeEnum result;

            if (Enum.TryParse(themeName, true, out result))
            {
                return result;
            }
            return (EsgThemeEnum)(-1);
        }

        private static EsgRpControversyLevelEnum GetControversyLevel(string controversyLevel)
        {

            EsgRpControversyLevelEnum result;

            if (Enum.TryParse(controversyLevel, true, out result))
            {
                return result;
            }
            return (EsgRpControversyLevelEnum)(-1);

        }

        public static EsgRpIndicatorDto ToDto(this ESGRpIndicator domainModel)
        {
            if (domainModel == null)
                return null;
            var esgRpIndicatorDto = new EsgRpIndicatorDto();
            esgRpIndicatorDto.Id = domainModel.Id;
            esgRpIndicatorDto.Name = domainModel.Name;
            esgRpIndicatorDto.Code = domainModel.Code;
            esgRpIndicatorDto.ClusterName = domainModel.Cluster;
            esgRpIndicatorDto.Theme = GetEsgTheme(domainModel.ThemeName);
            esgRpIndicatorDto.IsControversyIndicator = domainModel.IsControversyIndicator;
            esgRpIndicatorDto.AnswerCategory = domainModel.AnswerCategory;
            esgRpIndicatorDto.AnswerCategoryDescription = domainModel.AnswerCategoryDescription;

            esgRpIndicatorDto.Score = new EsgRpIndicatorScoreDto
            {
                RawScore = domainModel.RawScore != null ? Convert.ToDecimal(domainModel.RawScore.Value) : 0,
                Weight = domainModel.Weight != null ? Convert.ToDecimal(domainModel.Weight.Value) : 0,
                WeightedScore = domainModel.WeightedScore != null ? Convert.ToDecimal(domainModel.WeightedScore.Value) : 0,
                TrendType = (EsgRpIndicatorTrendTypeEnum?)domainModel.Trend
            };

            esgRpIndicatorDto.Commentary = domainModel.Comments;

            esgRpIndicatorDto.Ticboxes = !domainModel.Tickboxes.IsNullOrEmpty()
                ? domainModel.Tickboxes.Select(t => new EsgRpIndicatorTicboxDto { Checked = t.IsChecked, Description = t.Text })
                : Enumerable.Empty<EsgRpIndicatorTicboxDto>();

            esgRpIndicatorDto.Controversy = new EsgRpControversyDto
            {
                ControversyLevel = GetControversyLevel(domainModel.ControversyLevel.ToString(CultureInfo.InvariantCulture)),
                EventIndicators = !domainModel.EventIndicators.IsNullOrEmpty() ? domainModel.EventIndicators.Select(x => new EsgRpControversyEventIndicatorDto(x)) : Enumerable.Empty<EsgRpControversyEventIndicatorDto>(),
                OutlookType = (EsgRpIndicatorOutlookTypeEnum?)domainModel.OutlookScore
            };

            esgRpIndicatorDto.DataTable = !domainModel.DataTable.IsNullOrEmpty() ? domainModel.DataTable.Select(dt => new EsgRpNonRatedIndicatorValueDto { Name = dt.Name, Value = dt.Value, Year = dt.Year }) : Enumerable.Empty<EsgRpNonRatedIndicatorValueDto>(); return esgRpIndicatorDto;
        }

        public static EsgHistoricalPerformanceSummaryDto ToDto(this CompanyHistoricalPerformance domainModel)
        {
            var result = new EsgHistoricalPerformanceSummaryDto
            {
                Environment = new EsgEnvironmentHistoricalPerformanceSummaryDto()
                {
                    CompanyHistory = new List<EsgCorporateMonthlyScoreDto>(),
                    IndustryLeaderHistory = new List<EsgCorporateMonthlyScoreDto>(),
                    PeerGroupAvgHistory = new List<EsgCorporateMonthlyScoreDto>()
                },
                Governance = new EsgGovernanceHistoricalPerformanceSummaryDto
                {
                    CompanyHistory = new List<EsgCorporateMonthlyScoreDto>(),
                    IndustryLeaderHistory = new List<EsgCorporateMonthlyScoreDto>(),
                    PeerGroupAvgHistory = new List<EsgCorporateMonthlyScoreDto>()
                },
                Social = new EsgSocialHistoricalPerformanceSummaryDto
                {
                    CompanyHistory = new List<EsgCorporateMonthlyScoreDto>(),
                    IndustryLeaderHistory = new List<EsgCorporateMonthlyScoreDto>(),
                    PeerGroupAvgHistory = new List<EsgCorporateMonthlyScoreDto>()
                },
                Overall = new EsgOverallHistoricalPerformanceSummaryDto
                {
                    CompanyHistory = new List<EsgCorporateMonthlyScoreDto>(),
                    IndustryLeaderHistory = new List<EsgCorporateMonthlyScoreDto>(),
                    PeerGroupAvgHistory = new List<EsgCorporateMonthlyScoreDto>()
                }
            };

            if (domainModel != null)
            {
                domainModel.Last36Months.ForEach(hist =>
                {
                    result.Environment.CompanyHistory.Add(new EsgCorporateMonthlyScoreDto
                    {
                        Score = hist.EnvironmentScore < 0 ? (decimal?)null : Convert.ToDecimal(hist.EnvironmentScore),
                        Month = hist.Date.Month,
                        Year = hist.Date.Year
                    });
                    result.Environment.IndustryLeaderHistory.Add(
                        new EsgCorporateMonthlyScoreDto
                        {
                            Score = hist.EnvironmentBestInClass < 0 ? (decimal?)null : Convert.ToDecimal(hist.EnvironmentBestInClass),
                            Month = hist.Date.Month,
                            Year = hist.Date.Year
                        }
                        );
                    result.Environment.PeerGroupAvgHistory.Add(
                        new EsgCorporateMonthlyScoreDto
                        {
                            Score = hist.EnvironmentAverage < 0 ? (decimal?)null : Convert.ToDecimal(hist.EnvironmentAverage),
                            Month = hist.Date.Month,
                            Year = hist.Date.Year
                        }
                        );

                    result.Governance.CompanyHistory.Add(new EsgCorporateMonthlyScoreDto
                    {
                        Score = hist.GovernanceScore < 0 ? (decimal?)null : Convert.ToDecimal(hist.GovernanceScore),
                        Month = hist.Date.Month,
                        Year = hist.Date.Year
                    });
                    result.Governance.IndustryLeaderHistory.Add(
                        new EsgCorporateMonthlyScoreDto
                        {
                            Score = hist.GovernanceBestInClass < 0 ? (decimal?)null : Convert.ToDecimal(hist.GovernanceBestInClass),
                            Month = hist.Date.Month,
                            Year = hist.Date.Year
                        }
                        );
                    result.Governance.PeerGroupAvgHistory.Add(
                        new EsgCorporateMonthlyScoreDto
                        {
                            Score = hist.GovernanceAverage < 0 ? (decimal?)null : Convert.ToDecimal(hist.GovernanceAverage),
                            Month = hist.Date.Month,
                            Year = hist.Date.Year
                        }
                        );

                    result.Social.CompanyHistory.Add(new EsgCorporateMonthlyScoreDto
                    {
                        Score = hist.SocialScore < 0 ? (decimal?)null : Convert.ToDecimal(hist.SocialScore),
                        Month = hist.Date.Month,
                        Year = hist.Date.Year
                    });
                    result.Social.IndustryLeaderHistory.Add(
                        new EsgCorporateMonthlyScoreDto
                        {
                            Score = hist.SocialBestInClass < 0 ? (decimal?)null : Convert.ToDecimal(hist.SocialBestInClass),
                            Month = hist.Date.Month,
                            Year = hist.Date.Year
                        }
                        );
                    result.Social.PeerGroupAvgHistory.Add(
                        new EsgCorporateMonthlyScoreDto
                        {
                            Score = hist.SocialAverage < 0 ? (decimal?)null : Convert.ToDecimal(hist.SocialAverage),
                            Month = hist.Date.Month,
                            Year = hist.Date.Year
                        }
                        );

                    result.Overall.CompanyHistory.Add(new EsgCorporateMonthlyScoreDto
                    {
                        Score = hist.OverallScore < 0 ? (decimal?)null : Convert.ToDecimal(hist.OverallScore),
                        Month = hist.Date.Month,
                        Year = hist.Date.Year
                    });
                    result.Overall.IndustryLeaderHistory.Add(
                        new EsgCorporateMonthlyScoreDto
                        {
                            Score = hist.OverallBestInClass < 0 ? (decimal?)null : Convert.ToDecimal(hist.OverallBestInClass),
                            Month = hist.Date.Month,
                            Year = hist.Date.Year
                        }
                        );
                    result.Overall.PeerGroupAvgHistory.Add(
                        new EsgCorporateMonthlyScoreDto
                        {
                            Score = hist.OverallAverage < 0 ? (decimal?)null : Convert.ToDecimal(hist.OverallAverage),
                            Month = hist.Date.Month,
                            Year = hist.Date.Year
                        }
                        );
                });
            }
            return result;
        }

        public static EsgIndustryLeadPersonnelDto ToDto(this Analyst domainModel, string photoUrl)
        {
            if (domainModel == null)
                return null;
            return new EsgIndustryLeadPersonnelDto
            {
                Name = domainModel.FirstName + ' ' + domainModel.LastName,
                Email = domainModel.Email,
                PhotoUrl = photoUrl,
            };
        }

        public static EsgOverallPerformanceSummaryDto ToDto(this EsgOverallPerformanceSummary domainModel)
        {
            if (domainModel == null)
            {
                return null;
            }

            return new EsgOverallPerformanceSummaryDto
            {
                Overall = domainModel.Overall,
                Environment = domainModel.Environment,
                Social = domainModel.Social,
                Governance = domainModel.Governance,
                Percentile = domainModel.Percentile.ToDto(),
                Relative = domainModel.Relative.ToDto(),
                LastUpdate = domainModel.LastUpdate
            };
        }

        public static EsgRelativePositionDto ToDto(this EsgRelativePosition domainModel)
        {
            if (domainModel == null)
                return null;
            return new EsgRelativePositionDto
            {
                PositionSummary = domainModel.PositionSummary.ToDto(),
                MarketCapRangeFrom = domainModel.MarketCapRangeFrom,
                MarketCapRangeTo = domainModel.MarketCapRangeTo,
                TopList = domainModel.TopList.Select(item => item.ToDto()).ToArray(),
                PeersList = domainModel.PeersList.Select(item => item.ToDto()).ToArray(),
            };
        }


        private static EsgCorporateScoreDto ToDto(this EsgCorporateScore domainModel)
        {
            return new EsgCorporateScoreDto
            {
                CompanyId = domainModel.CompanyId,
                CompanyName = domainModel.CompanyName,
                Score = domainModel.Score,
            };
        }

        private static EsgPercentileSummaryDto ToDto(this EsgPercentileSummary domainModel)
        {
            return new EsgPercentileSummaryDto
            {
                ComparativeGroupPercentileRank = domainModel.Percentile,
                EsgPosition = domainModel.EsgPosition,
                IsInReferenceUniverse = domainModel.IsInReferenceUniverse
            };
        }

        private static EsgRelativePositionSummaryDto ToDto(this EsgRelativePositionSummary domainModel)
        {
            return new EsgRelativePositionSummaryDto
            {
                ComparativeGroupRank = domainModel.ComparativeGroupRank,
                ComparativeGroupSize = domainModel.ComparativeGroupSize,
                EsgPosition = domainModel.EsgPosition,
                IsInReferenceUniverse = domainModel.IsInReferenceUniverse
            };
        }
    }
}